package com.jphoebe.plugin.mybatis.intention.generate.mapper;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.impl.source.xml.XmlFileImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlTag;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBList;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Functions;
import com.intellij.util.IncorrectOperationException;
import com.jphoebe.plugin.mybatis.dom.attribute.GroupTwo;
import com.jphoebe.plugin.mybatis.dom.attribute.Insert;
import com.jphoebe.plugin.mybatis.dom.attribute.Mapper;
import com.jphoebe.plugin.mybatis.generate.SimpleSqlGenerate;
import com.jphoebe.plugin.mybatis.intention.GenericIntention;
import com.jphoebe.plugin.mybatis.service.EditorService;
import com.jphoebe.plugin.mybatis.service.JavaService;
import com.jphoebe.plugin.mybatis.utils.jetbrain.JetbrainDomUtil;
import com.jphoebe.plugin.mybatis.utils.jetbrain.JetbrainMapperUtil;
import org.apache.commons.collections.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * @author yanglin
 * @update JPhoebe
 * @function 生成mapper里面的语句方法
 */
public class GenerateMethodStatementIntention extends GenericIntention {

    public GenerateMethodStatementIntention() {
        super(GenerateMethodStatementChooser.INSTANCE);
    }

    @NotNull
    @Override
    public String getText() {
        return "[Mybatis] Simple Generate new statement";
    }

    @Override
    public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
        PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
//        StatementGenerator.applyGenerate(PsiTreeUtil.getParentOfType(element, PsiMethod.class));
        final JBList tagList = new JBList(Arrays.asList("insert", "delete", "update", "select"));
        showJBPopup(tagList,
                "请选择SQL语句类型",
                editor,
                element,
                ()->{
                    String sqlType = tagList.getSelectedValue().toString();
                    applyGenerate(PsiTreeUtil.getParentOfType(element, PsiMethod.class), editor, element, sqlType);
        });
    }

    public void applyGenerate(@Nullable final PsiMethod method, Editor editor, PsiElement element, @NotNull String sqlType) {
        PsiClass psiClass = method.getContainingClass();
        if (null == psiClass) {
            return;
        }
        CommonProcessors.CollectProcessor<Mapper> processor = new CommonProcessors.CollectProcessor<Mapper>();
        JavaService.getInstance(method.getProject()).process(psiClass, processor);
        final List<Mapper> mappers = Lists.newArrayList(processor.getResults());
        if (1 == mappers.size()) {
            setupTag(method, Iterables.getOnlyElement(mappers, null), sqlType, editor);
        } else if (mappers.size() > 1) {
            Collection<String> paths = Collections2.transform(mappers, new Function<Mapper, String>() {
                @Override
                public String apply(Mapper mapper) {
                    VirtualFile vf = mapper.getXmlTag().getContainingFile().getVirtualFile();
                    if (null == vf) {
                        return "";
                    }
                    return vf.getCanonicalPath();
                }
            });
            final JBList tagList = new JBList(paths);
            showJBPopup(tagList,
                    "选择要添加SQL的目标xml文件",
                    editor,
                    element,
                    ()->{
                        Mapper mapper = mappers.get(tagList.getSelectedIndex());
                        setupTag(method, mapper, sqlType, editor);
                    });

        }
    }

    private void setupTag(PsiMethod method, Mapper mapper, String sqlType, Editor editor) {
//            PsiClass clazz = PsiTreeUtil.getParentOfType(element, PsiClass.class);
        PsiClass clazz = method.getContainingClass();
        if(clazz.getQualifiedName().equals(mapper.getNamespace().toString())){
            WriteCommandAction.runWriteCommandAction(method.getProject(), ()->{
                GroupTwo target = SimpleSqlGenerate.addGenerate(mapper, sqlType, method, editor);
                if(target==null){
                    return ;
                }
                target.getId().setStringValue(method.getName());
                target.setValue("\n\n");
                XmlTag tag = target.getXmlTag();
                TextRange textRange = tag.getValue().getTextRange();
                int offset = (textRange.getStartOffset()+textRange.getEndOffset())/2+5;
                EditorService editorService = EditorService.getInstance(method.getProject());
                editorService.format(tag.getContainingFile(), tag);
                editorService.scrollTo(tag, offset);
            });
        }
    }

    private void showJBPopup(JBList tagList, String title, Editor editor, PsiElement element, Runnable runnable){
        PopupChooserBuilder builder = new PopupChooserBuilder(tagList);
        builder.setTitle(title);
        builder.setItemChoosenCallback(runnable);
        final JBPopup popup = builder.createPopup();
        popup.showInBestPositionFor(editor);
    }

}
